{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyspark import SparkContext\n",
    "from pyspark.sql import SparkSession\n",
    "from pyspark.sql.types import *\n",
    "from pyspark.sql import Row\n",
    "from pyspark.sql import Column\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc=SparkContext(appName=\"pg_dataframe\")      \n",
    "spark=SparkSession.builder.appName('pg_dataframe') \\\n",
    "        .master(\"Yct201811021847\") \\\n",
    "        .getOrCreate()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "db=spark.read.format('jdbc').options(\n",
    "        url='jdbc:postgresql://localhost:5432/northwind',\n",
    "        user='postgres',\n",
    "        password='iamroot'\n",
    "        #query=\"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------+\n",
      "|          table_name|\n",
      "+--------------------+\n",
      "|          categories|\n",
      "|customercustomerdemo|\n",
      "|customerdemographics|\n",
      "|           customers|\n",
      "|           employees|\n",
      "| employeeterritories|\n",
      "|       order_details|\n",
      "|              orders|\n",
      "|            products|\n",
      "|              region|\n",
      "|            shippers|\n",
      "|        shippers_tmp|\n",
      "|           suppliers|\n",
      "|         territories|\n",
      "|            usstates|\n",
      "+--------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#db.option('query',\"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\").load().show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "categories_df = db.option(\"dbtable\",\"categories\").load()\n",
    "products_df = db.option(\"dbtable\",\"products\").load()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+----------+--------------+--------------------+-------+\n",
      "|categoryid|  categoryname|         description|picture|\n",
      "+----------+--------------+--------------------+-------+\n",
      "|         1|     Beverages|Soft drinks, coff...|     []|\n",
      "|         2|    Condiments|Sweet and savory ...|     []|\n",
      "|         3|   Confections|Desserts, candies...|     []|\n",
      "|         4|Dairy Products|             Cheeses|     []|\n",
      "|         5|Grains/Cereals|Breads, crackers,...|     []|\n",
      "+----------+--------------+--------------------+-------+\n",
      "only showing top 5 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "categories_df.show(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---------+--------------------+----------+----------+-------------------+---------+------------+------------+------------+------------+\n",
      "|productid|         productname|supplierid|categoryid|    quantityperUnit|unitprice|unitsinstock|unitsonorder|reorderlevel|discontinued|\n",
      "+---------+--------------------+----------+----------+-------------------+---------+------------+------------+------------+------------+\n",
      "|        1|                Chai|         8|         1| 10 boxes x 30 bags|     18.0|          39|           0|          10|           1|\n",
      "|        2|               Chang|         1|         1| 24 - 12 oz bottles|     19.0|          17|          40|          25|           1|\n",
      "|        3|       Aniseed Syrup|         1|         2|12 - 550 ml bottles|     10.0|          13|          70|          25|           0|\n",
      "|        4|Chef Anton's Caju...|         2|         2|     48 - 6 oz jars|     22.0|          53|           0|           0|           0|\n",
      "|        5|Chef Anton's Gumb...|         2|         2|           36 boxes|    21.35|           0|           0|           0|           1|\n",
      "+---------+--------------------+----------+----------+-------------------+---------+------------+------------+------------+------------+\n",
      "only showing top 5 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "products_df.show(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "root\n",
      " |-- productid: short (nullable = true)\n",
      " |-- productname: string (nullable = true)\n",
      " |-- supplierid: short (nullable = true)\n",
      " |-- categoryid: short (nullable = true)\n",
      " |-- quantityperUnit: string (nullable = true)\n",
      " |-- unitprice: float (nullable = true)\n",
      " |-- unitsinstock: short (nullable = true)\n",
      " |-- unitsonorder: short (nullable = true)\n",
      " |-- reorderlevel: short (nullable = true)\n",
      " |-- discontinued: integer (nullable = true)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "products_df.printSchema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "categories_df.createTempView('categories')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "products_df.createTempView('products')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+----------+--------------+--------------------+-------+\n",
      "|categoryid|  categoryname|         description|picture|\n",
      "+----------+--------------+--------------------+-------+\n",
      "|         1|     Beverages|Soft drinks, coff...|     []|\n",
      "|         2|    Condiments|Sweet and savory ...|     []|\n",
      "|         3|   Confections|Desserts, candies...|     []|\n",
      "|         4|Dairy Products|             Cheeses|     []|\n",
      "|         5|Grains/Cereals|Breads, crackers,...|     []|\n",
      "+----------+--------------+--------------------+-------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "spark.sql('SELECT * FROM categories LIMIT 5').show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---------+--------------------+----------+----------+-------------------+---------+------------+------------+------------+------------+\n",
      "|productid|         productname|supplierid|categoryid|    quantityperUnit|unitprice|unitsinstock|unitsonorder|reorderlevel|discontinued|\n",
      "+---------+--------------------+----------+----------+-------------------+---------+------------+------------+------------+------------+\n",
      "|        1|                Chai|         8|         1| 10 boxes x 30 bags|     18.0|          39|           0|          10|           1|\n",
      "|        2|               Chang|         1|         1| 24 - 12 oz bottles|     19.0|          17|          40|          25|           1|\n",
      "|        3|       Aniseed Syrup|         1|         2|12 - 550 ml bottles|     10.0|          13|          70|          25|           0|\n",
      "|        4|Chef Anton's Caju...|         2|         2|     48 - 6 oz jars|     22.0|          53|           0|           0|           0|\n",
      "|        5|Chef Anton's Gumb...|         2|         2|           36 boxes|    21.35|           0|           0|           0|           1|\n",
      "+---------+--------------------+----------+----------+-------------------+---------+------------+------------+------------+------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "spark.sql('SELECT * FROM products LIMIT 5').show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = spark.sql('SELECT categoryname , productname , quantityperUnit , unitprice , \\\n",
    "                         unitsinstock , unitsonorder , reorderlevel , discontinued \\\n",
    "                 FROM products  prd LEFT JOIN categories cate ON prd.categoryid = cate.categoryid \\\n",
    "                 ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "pyspark.sql.dataframe.DataFrame"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'data' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m\u001b[0m",
      "\u001b[1;31mNameError\u001b[0mTraceback (most recent call last)",
      "\u001b[1;32m<ipython-input-1-8f71a56b37a6>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mdata\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcreateOrReplaceTempView\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'product_categoryname'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m: name 'data' is not defined"
     ]
    }
   ],
   "source": [
    "data.createOrReplaceTempView('product_categoryname')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "group_data = spark.sql('SELECT categoryname , AVG(unitprice) avg_unitprice , AVG(unitsinstock) avg_unitsinstock ,  \\\n",
    "                               MAX(reorderlevel) max_reorderlevel ,  COUNT(*) count_num  \\\n",
    "                               FROM product_categoryname   \\\n",
    "                               GROUP BY categoryname   \\\n",
    "                      ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------+------------------+------------------+----------------+---------+\n",
      "|  categoryname|     avg_unitprice|  avg_unitsinstock|max_reorderlevel|count_num|\n",
      "+--------------+------------------+------------------+----------------+---------+\n",
      "|Dairy Products|28.729999923706053|              39.3|              30|       10|\n",
      "|  Meat/Poultry| 54.00666666030884|              27.5|              20|        6|\n",
      "|    Condiments|22.854166825612385|             42.25|              25|       12|\n",
      "|     Beverages|37.979166666666664|46.583333333333336|              30|       12|\n",
      "|Grains/Cereals|             20.25|              44.0|              30|        7|\n",
      "|       Seafood|20.682499885559082|58.416666666666664|              30|       12|\n",
      "|   Confections|  25.1600000674908|29.692307692307693|              30|       13|\n",
      "|       Produce|32.369999694824216|              20.0|              10|        5|\n",
      "+--------------+------------------+------------------+----------------+---------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "group_data.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "group_data.write.parquet(\"product_categoryname.parquet\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+------------+------------------+------------------+---------+------------+------------+------------+------------+\n",
      "|categoryname|       productname|   quantityperUnit|unitprice|unitsinstock|unitsonorder|reorderlevel|discontinued|\n",
      "+------------+------------------+------------------+---------+------------+------------+------------+------------+\n",
      "|   Beverages|              Chai|10 boxes x 30 bags|     18.0|          39|           0|          10|           1|\n",
      "|   Beverages|             Chang|24 - 12 oz bottles|     19.0|          17|          40|          25|           1|\n",
      "|   Beverages|Guaraná Fantástica|  12 - 355 ml cans|      4.5|          20|           0|           0|           1|\n",
      "+------------+------------------+------------------+---------+------------+------------+------------+------------+\n",
      "only showing top 3 rows\n",
      "\n",
      "+--------------+------------------+----------------+----------------+---------+\n",
      "|  categoryname|     avg_unitprice|avg_unitsinstock|max_reorderlevel|count_num|\n",
      "+--------------+------------------+----------------+----------------+---------+\n",
      "|Dairy Products|28.729999923706053|            39.3|              30|       10|\n",
      "|  Meat/Poultry| 54.00666666030884|            27.5|              20|        6|\n",
      "|    Condiments|22.854166825612385|           42.25|              25|       12|\n",
      "+--------------+------------------+----------------+----------------+---------+\n",
      "only showing top 3 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "data.show(3)\n",
    "group_data.show(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "# csv 操作\n",
    "iris_df=spark.read.csv('iris_dataset.csv',header=True, inferSchema=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "stringCSV = spark.sparkContext.parallelize([\n",
    "                    (1, \"setosa\", u\"山鸢尾\"),\n",
    "                    (2, \"versicolor\", u\"杂色鸢尾\"),\n",
    "                    (3, \"virginica\", u\"维吉尼亚鸢尾\")])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "schema = StructType([StructField(\"id\", LongType(), True),\n",
    "                    StructField(\"english_name\", StringType(), True),\n",
    "                    StructField(\"chinese_name\", StringType(), True)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---+------------+------------+\n",
      "| id|english_name|chinese_name|\n",
      "+---+------------+------------+\n",
      "|  1|      setosa|      山鸢尾|\n",
      "|  2|  versicolor|    杂色鸢尾|\n",
      "+---+------------+------------+\n",
      "only showing top 2 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "name_df = spark.createDataFrame(stringCSV,schema)\n",
    "name_df.show(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "iris_df.createOrReplaceTempView('iris_data')\n",
    "name_df.createOrReplaceTempView('iris_name')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "data=spark.sql('SELECT data.* , name.chinese_name FROM iris_data data \\\n",
    "                    INNER JOIN iris_name name \\\n",
    "                    ON data.species = name.english_name \\\n",
    "          ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+------------+-----------+------------+-----------+-------+------------+\n",
      "|sepal_length|sepal_width|petal_length|petal_width|species|chinese_name|\n",
      "+------------+-----------+------------+-----------+-------+------------+\n",
      "|         5.0|        3.3|         1.4|        0.2| setosa|      山鸢尾|\n",
      "|         5.3|        3.7|         1.5|        0.2| setosa|      山鸢尾|\n",
      "|         4.6|        3.2|         1.4|        0.2| setosa|      山鸢尾|\n",
      "+------------+-----------+------------+-----------+-------+------------+\n",
      "only showing top 3 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "data.show(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "spark.catalog.dropTempView('iris_data')\n",
    "spark.catalog.dropTempView('iris_name')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+------------+-----------+------------+-----------+-------+------------+\n",
      "|sepal_length|sepal_width|petal_length|petal_width|species|chinese_name|\n",
      "+------------+-----------+------------+-----------+-------+------------+\n",
      "|         5.0|        3.3|         1.4|        0.2| setosa|      山鸢尾|\n",
      "|         5.3|        3.7|         1.5|        0.2| setosa|      山鸢尾|\n",
      "|         4.6|        3.2|         1.4|        0.2| setosa|      山鸢尾|\n",
      "+------------+-----------+------------+-----------+-------+------------+\n",
      "only showing top 3 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "data.show(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Json\n",
    "schema = StructType([\n",
    "    StructField(\"id\", StringType(), True), \n",
    "    StructField(\"name\", StringType(), True),    \n",
    "    StructField(\"times\", StringType(), True),\n",
    "    StructField(\"url\", StringType(), True),\n",
    "    StructField(\"user\", StringType(), True),\n",
    "    StructField(\"manager\", StringType(), True)\n",
    "])\n",
    "df = spark.read.json('test.json',schema)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---+------+-----+--------------------+----+-------+\n",
      "| id|  name|times|                 url|user|manager|\n",
      "+---+------+-----+--------------------+----+-------+\n",
      "|  1|Google|    3|http://www.google...|nick|      7|\n",
      "|  2| Baidu|    2|http://www.baidu.com|mike|      1|\n",
      "+---+------+-----+--------------------+----+-------+\n",
      "only showing top 2 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "df.show(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.createOrReplaceTempView('webbrowser')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [],
   "source": [
    "data=spark.sql(\"SELECT  A.id , A.name , A.times , A.url  , A.user , B.user manager \\\n",
    "           FROM webbrowser A \\\n",
    "           LEFT JOIN webbrowser B     \\\n",
    "           ON A.manager = B.id  \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---+------+-----+--------------------+----+-------+\n",
      "| id|  name|times|                 url|user|manager|\n",
      "+---+------+-----+--------------------+----+-------+\n",
      "|  1|Google|    3|http://www.google...|nick|  allen|\n",
      "|  2| Baidu|    2|http://www.baidu.com|mike|   nick|\n",
      "|  3|  bing|    1| http://www.bing.com|kate|   nick|\n",
      "+---+------+-----+--------------------+----+-------+\n",
      "only showing top 3 rows\n",
      "\n"
     ]
    }
   ],
   "source": [
    "data.show(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [],
   "source": [
    "spark.catalog.dropTempView('webbrowser')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyspark.sql.types import IntegerType"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyspark.sql.functions import udf\n",
    "import pandas as pd\n",
    "import numpy as  np\n",
    "square_udf_int = udf(lambda z: abs(z), IntegerType())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "root\n",
      " |-- floats: double (nullable = true)\n",
      " |-- integer_arrays: array (nullable = true)\n",
      " |    |-- element: long (containsNull = true)\n",
      " |-- integers: long (nullable = true)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "df_pd = pd.DataFrame(\n",
    "    data={'integers': [1, 2, 3],\n",
    "     'floats': [-1.0, 0.5, 2.7],\n",
    "     'integer_arrays': [[1, 2], [3, 4, 5], [6, 7, 8, 9]]}\n",
    ")\n",
    "df = spark.createDataFrame(df_pd)\n",
    "df.printSchema()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------+------+-----------+-------------+\n",
      "|integers|floats|int_squared|float_squared|\n",
      "+--------+------+-----------+-------------+\n",
      "|       1|  -1.0|          1|         null|\n",
      "|       2|   0.5|          2|         null|\n",
      "|       3|   2.7|          3|         null|\n",
      "+--------+------+-----------+-------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "(\n",
    "    df.select('integers',\n",
    "              'floats',\n",
    "              square_udf_int('integers').alias('int_squared'),\n",
    "              square_udf_int('floats').alias('float_squared'))\n",
    "    .show()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.createOrReplaceTempView('udftest')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+---+---------------------+\n",
      "| id|squaredWithPython(id)|\n",
      "+---+---------------------+\n",
      "|  1|                    2|\n",
      "|  2|                    3|\n",
      "|  3|                    4|\n",
      "|  4|                    5|\n",
      "|  5|                    6|\n",
      "|  6|                    7|\n",
      "|  7|                    8|\n",
      "|  8|                    9|\n",
      "|  9|                   10|\n",
      "| 10|                   11|\n",
      "| 11|                   12|\n",
      "| 12|                   13|\n",
      "| 13|                   14|\n",
      "| 14|                   15|\n",
      "| 15|                   16|\n",
      "| 16|                   17|\n",
      "| 17|                   18|\n",
      "| 18|                   19|\n",
      "| 19|                   20|\n",
      "+---+---------------------+\n",
      "\n"
     ]
    }
   ],
   "source": [
    "spark.range(1, 20).registerTempTable(\"test\")\n",
    "def squared(s):\n",
    "  return s+1\n",
    "spark.udf.register(\"squaredWithPython\", squared)\n",
    "\n",
    "spark.sql(\" SELECT id, squaredWithPython(id)  FROM test \").show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
